package com.shiguiwu.springmybatis.netty.simple;

import com.shiguiwu.springmybatis.netty.simple.handler.NettyServiceHandler;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import lombok.extern.slf4j.Slf4j;

/**
 * @description: netty service
 * @author: stone
 * @date: Created by 2021/12/2 20:45
 * @version: 1.0.0
 * @pakeage: com.shiguiwu.springmybatis.netty.simple
 */
@Slf4j
public class NettyService {

    public static void main(String[] args) throws InterruptedException {
        /**
         * 1,创建两个线程组bossGroup，workerGroup
         * 2,bossGroup只负责接受请求，真正与客户端业务处理，只会由workerGroup组成
         * 3,两个线程组子线程（NioEventLoop）的个数是 cpu * 2
         *
         */
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();

        try {
            //创建服务器的启动对象
            ServerBootstrap bootstrap = new ServerBootstrap();

            //链式编程
            bootstrap.group(bossGroup, workerGroup)
                    //设置使用NioSocketChannel 作为服务器的通道实现
                    .channel(NioServerSocketChannel.class)
                    //设置线程队列等待个数
                    .option(ChannelOption.SO_BACKLOG, 128)
                    //设置保持活动链接状态
                    .childOption(ChannelOption.SO_KEEPALIVE, true)
                    // 该 handler对应 bossGroup , childHandler 对应 workerGroup
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            log.info("客户 socketChannel hashcode= {}" , socketChannel.hashCode()); //可以使用一个集合管理 SocketChannel， 再推送消息时，可以将业务加入到各个channel 对应的 NIOEventLoop 的 taskQueue 或者 scheduleTaskQueue
                            socketChannel.pipeline().addLast(new NettyServiceHandler());

                        }
                    });

           log.error("server is ready ~~~~");

            //绑定一个端口并且生成一个ChannelFuture 对象
            ChannelFuture future = bootstrap.bind(8999).sync();
            //给future对象增加监听器
            future.addListener(f -> {
                if (f.isSuccess()) {
                    log.info("监听端口8999成功");
                } else {
                    log.info("监听端口8999失败");
                }

            });

            //对关闭通道进行监听
            future.channel().closeFuture().sync();
        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }

    }
}
